#include "5m3x.h"
#include "curtain.h"
#include "help_curtain.h"
#include "dac1.h"
#include "led.h"
#include "tim3.h"
#include "tim4.h"
#include "tim5.h"
#include "font.h"

const uint16_t default_scan_list_5m3x[6] = {0xFFFF, 0x9249, 0x9249, 0x9249, 0x9249, 0x9249};

/*
wait_time_ms          等待多长时间再开始打开光栅
time_out_ms           多长时间退出，算为超时
how_many              需要检测到几个红外光线拦断才认为是到达了
interval_us           检测间隔
*/
uint8_t one_point_test(uint8_t id, uint16_t wait_time_ms, uint16_t time_out_ms, uint16_t how_many, uint16_t valid_times, uint16_t interval_us)
{
    uint16_t blocked_times = 0;
    // 进入程序后，开始计时器1
    tim5_start_timer(1);
    tim5_wait_timer_reached_us(1, wait_time_ms * 1000);
    // 测试，并等待超时
    while (1)
    {
        // 每发射一次光线，就重置一下计时器2
        tim5_start_timer(2);
        if (tim5_read_started_time_us(1) >= time_out_ms * 1000)
        {
            return POINT_TIMEOUT;
        }
        if (curtain_blocked_light_count(id, default_scan_list_5m3x[id - 1]) >= how_many)
        {
            blocked_times++;
            if (blocked_times >= valid_times)
            {
                return POINT_REACHED;
            }
        }
        tim5_wait_timer_reached_us(2, interval_us);
    }
}

void test_5m3x()
{
    uint16_t time[6] = {0, 0, 0, 0, 0, 0};
    if (curtains_temp_read_scanlist(6))
    {
        led_display_infomation_and_wait_once((uint8_t *)str_5m3x_03);
    }
    static_display_mode(); // 静态显示模式
    Delay_ms(1);           // 等待转换完成
    display_static_text((uint8_t *)str_5m3x_02);
    while (1)
    {
        ///////////////////////////////////////////////////// 一号一直未踩
        while (curtain_blocked_light_count(1, default_scan_list_5m3x[0]) == 0)
        {
        }
        ///////////////////////////////////////////////////// 踩到一号了,等待从1号离开
        watch(WatchReset);
        dac1_play_by_index(SND_READY, 1);
        while (curtain_blocked_light_count(1, default_scan_list_5m3x[0]) >= 1)
        {
        }
        watch(WatchStart);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看2号何时到
        if (one_point_test(2, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 1, 2, TEST_INTERVAL) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        time[0] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看3号何时到
        if (one_point_test(3, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 1, 2, TEST_INTERVAL) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        time[1] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看4号何时到
        if (one_point_test(4, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 1, 2, TEST_INTERVAL) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        time[2] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看3号何时到
        if (one_point_test(3, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 1, 2, TEST_INTERVAL) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        time[3] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看5号何时到
        if (one_point_test(5, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 1, 2, TEST_INTERVAL) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        time[4] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 0);
        ///////////////////////////////////////////////////// 查看6号何时到
        if (one_point_test(6, DELAY_OPEN_CURTAIN, TIMEOUT_5M3X, 2, 2, TEST_INTERVAL * 2.5) == POINT_TIMEOUT)
        {
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            continue;
        }
        watch(WatchStop);
        time[5] = watch(WatchGetTime);
        dac1_play_n_ms_by_index(SND_987HZ, 100, 1);
        ///////////////////////////////////////////////////// 显示结果
        led_print_one_ascii(' ', 6); // 清除秒字
        led_print_one_ascii(' ', 7); // 清除秒字
        // 显示每道时间
        for (uint8_t i = 0; i < 6; i++)
        {
            uint16_t tmp = i == 0 ? (time[i] - 70) / 6 : (time[i] - time[i - 1] - 70) / 6;
            tmp = tmp == 0 ? 1 : tmp;
            tmp = tmp > 16 ? 16 : tmp;
            Display16bit(i * 2 + 2, 6, 0xFFFF << (16 - tmp));
        }
        Delay_ms(200);
        speak_time(watch(WatchGetTime));
        ///////////////////////////////////////////////////// 结束
    }
}

/*
    开机前  接0个传感器也不接        用于调试位置
    开机前  接1个传感器             用于扫描不良光线
    开机前  接12个传感器            进入测试
    开机前  接其它数量传感器         485通讯测试

*/
void poweron_sequence_for_5m3x()
{
    led_display_infomation_and_wait_once((uint8_t *)str_5m3x_01); // 显示仪器名称 五三测试仪
    dac1_play_by_index(SND_440HZ, 1);                             // 提示音
    usart1_init_with_RXNE(BAUD_1M);                               // 1M通讯
    switch (curtain_online_count(6))
    {
    case 0:
        curtains_light_status_display(6, (uint16_t *)default_scan_list_5m3x, 6000, 2200, 1);
        break;

    case 1:                                                                                       // 1个在线
        curtain_test_and_block_some_light(1, 6, 10000, 1700, (uint16_t *)default_scan_list_5m3x); // 测试光线情况
        if (curtain_online_count(6) == 12)
        {
            test_5m3x(); // 进入测试
        }
        else
        {
            curtains_485_test(6); // 调试通讯
        }
        break;

    case 12:         // 全在线
        test_5m3x(); // 五三测试程序
        break;

    default:
        curtains_485_test(6);
        break;
    }
}